package com.wuhao.code.check.model.base

import com.aegis.kotlin.toUnderlineCase
import com.aegis.mybatis.xmlless.AnnotatedElementDetailInfo
import com.aegis.mybatis.xmlless.AnnotationSupport
import com.aegis.mybatis.xmlless.constant.Annotations
import com.aegis.mybatis.xmlless.model.XmllessTableFieldInfo
import com.aegis.mybatis.xmlless.model.XmllessTableInfo
import com.aegis.mybatis.xmlless.model.base.BaseClassWrapper
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiField
import com.wuhao.code.check.getStringAnnoValue
import com.wuhao.code.check.hasAnnotation
import com.wuhao.code.check.toAnnotationElementWrapper
import org.jetbrains.kotlin.psi.KtDeclaration

/**
 *
 * @author 吴昊
 * @date 2024/1/26 11:12
 * @since v0.0.0
 * @version 1.0
 */

abstract class BasePsiClassWrapper<T : PsiElement>(
    val classElement: T
) : BaseClassWrapper {

  protected fun createFields(): List<AnnotatedElementDetailInfo> {
    val allFields = getClassFields()

    return allFields.filter {
      !it.hasAnnotation("kotlin.jvm.Transient") && !it.hasAnnotation(Annotations.Jakarta.TRANSIENT) && !it.hasAnnotation(
          Annotations.Javax.TRANSIENT
      )
    }.map { property ->
      AnnotatedElementDetailInfo(property.toAnnotationElementWrapper())
    }
  }


  abstract fun getClassFields(): List<PsiElement>

  protected fun getKeyColumn(keyField: PsiElement?): String? {
    if (keyField == null) {
      return null
    }
    AnnotationSupport.CUSTOM_COLUMN_ANNOTATIONS.forEach {
      if (keyField.hasAnnotation(it)) {
        return keyField.getStringAnnoValue(it, "name")!!
      }
    }
    if (keyField.hasAnnotation(Annotations.Plus.ID)) {
      return keyField.getStringAnnoValue(Annotations.Plus.ID, "value")!!
    }
    return when (keyField) {
      is PsiField      -> keyField.name.toUnderlineCase().lowercase()
      is KtDeclaration -> keyField.name?.toUnderlineCase()?.lowercase()
      else             -> error("无法解析主键字段")
    }
  }

  private fun resolveFromEntity(
      targetEntity: String, targetProperty: String, joinEntityTableInfo: XmllessTableInfo
  ): String {
    return joinEntityTableInfo.tableFields.find { it.property == targetProperty }?.column
      ?: error("无法解析${targetEntity}的属性${targetProperty}对应的数据库字段")
  }

  protected abstract fun resolveTableFields(
      modelType: T
  ): List<XmllessTableFieldInfo>

  protected abstract fun <E : PsiElement> createFieldByProperty(
      field: E
  ): XmllessTableFieldInfo
}
